package com.jms.framework.jdbc.transaction;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * 实现了TransactionManagement接口的通用事务管理类。
 * 提供了事务的开始、提交、回滚和关闭等操作功能。
 * @author JMS
 * @version 1.0.0
 * @since 2025-01-26
 */
public class GeneralTransactionManagement implements TransactionManagement {

    // 使用ThreadLocal来存储每个线程各自的事务信息
    private static final ThreadLocal<Transaction> transactionThreadLocal = new ThreadLocal<>();
    // 日志记录器，用于记录事务操作的日志信息
    private static final Logger logger = LogManager.getLogger(GeneralTransactionManagement.class);

    public GeneralTransactionManagement() {
    }


    /**
     * 获取当前线程的数据库连接。
     * 如果当前线程没有活动的事务，则返回null。
     * @return 当前线程的数据库连接或null
     */
    @Override
    public Connection getCurrentConnection() {
        Transaction transaction = transactionThreadLocal.get();
        return transaction != null ? transaction.getConnection() : null;
    }

    /**
     * 开始一个新的事务。
     * 如果成功获取到数据库连接，将自动提交设置为false，并在ThreadLocal中保存事务信息。
     * 如果出现异常，将记录错误日志并关闭事务。
     */
    @Override
    public void begin() {
        Connection connection;
        Transaction transaction = new Transaction(String.format("Transaction [%s]", System.currentTimeMillis()));
        try {
            connection = TransactionManagement.getDataSource().getConnection();
            transaction.setConnection(connection);
            connection.setAutoCommit(false);
            transactionThreadLocal.set(transaction);
            logger.info("Begin Transaction: " + transaction.getTransactionName());
        } catch (Exception e) {
            logger.error("Failed to begin Transaction: " + transaction.getTransactionName(), e);
            close();
        }
    }

    /**
     * 提交当前事务。
     * 如果事务存在，提交事务并设置事务为非活动状态。
     * 如果出现异常，将记录错误日志并关闭事务。
     */
    @Override
    public void commit() {
        Transaction transaction = transactionThreadLocal.get();
        if (transaction != null) {
            try {
                Connection connection = transaction.getConnection();
                connection.commit();
                transaction.setActive(false);
                logger.info("Commit Transaction: " + transaction.getTransactionName());
            } catch (Exception e) {
                logger.error("Failed to commit Transaction: " + transaction.getTransactionName(), e);
                close();
            }
        }
    }

    /**
     * 回滚当前事务。
     * 如果事务存在，回滚事务。
     * 如果出现异常，将记录错误日志并关闭事务。
     */
    @Override
    public void rollback() {
        Transaction transaction = transactionThreadLocal.get();
        if (transaction != null) {
            try {
                Connection connection = transaction.getConnection();
                connection.rollback();
                logger.info("Rollback Transaction: " + transaction.getTransactionName());
            } catch (Exception e) {
                logger.error("Failed to rollback Transaction: " + transaction.getTransactionName(), e);
                close();
            }
        }
    }

    /**
     * 关闭当前事务。
     * 如果事务存在，关闭事务的数据库连接并在ThreadLocal中移除事务信息。
     * 如果出现异常，将记录错误日志。
     */
    @Override
    public void close() {
        Transaction transaction = transactionThreadLocal.get();
        if (transaction != null) {
            try {
                Connection connection = transaction.getConnection();
                connection.close();
                transaction.setOpen(false);
                transactionThreadLocal.remove();
                logger.info("Close Transaction: " + transaction.getTransactionName());
            } catch (SQLException e) {
                logger.error("Failed to close Transaction: " + transaction.getTransactionName(), e);
            }
        }
    }

    /**
     * 检查当前事务是否处于活动状态。
     * @return 如果当前事务处于活动状态，则返回true；否则返回false
     */
    @Override
    public boolean transactionIsActive() {
        Transaction transaction = transactionThreadLocal.get();
        return transaction != null && transaction.isActive();
    }

    /**
     * 检查当前事务是否处于开启状态。
     * @return 如果当前事务处于开启状态，则返回true；否则返回false
     */
    @Override
    public boolean transactionIsOpen() {
        Transaction transaction = transactionThreadLocal.get();
        return transaction != null && transaction.isOpen();
    }
}
